#pragma once
#include <windows.h>

#include "CustomTree.h"

namespace core {
    
    namespace component{
        typedef UINT_PTR ID_T;
        typedef BOOL BOOL_T;

        enum MenuID : int{
            MAIN_RIGHT_CLICK_POPMENU,
            _TAIL
        };
        enum MenuItemID : int{
            EXIT_PROGRAM
        };

        template<typename T>
        class ComponentInstance{
        public:
            ComponentInstance(T handle){
                Handle = handle;
            }
            ComponentInstance(ComponentInstance && r_val){
                Handle = r_val.Handle;
                r_val.Handle = NULL;
            }
            virtual T GetHandle(){
                return Handle;
            }
            virtual ~ComponentInstance() = 0; 
        protected:
            T Handle;
        };

        template <typename T>
        ComponentInstance<T>::~ComponentInstance(){}

        template<typename T>
        class IComponent{
            virtual T CreateInstance() = 0;
        };

        class MenuInstance : public ComponentInstance<HMENU>{
        public:
            MenuInstance(HMENU handle);
            virtual ~MenuInstance();
        };

        class IMenuItem{
        public:
            virtual BOOL_T AppendToMenu(HMENU h_menu) = 0;

            virtual ID_T GetId() = 0;

            virtual LPCTSTR GetDisplayName() = 0;
        protected:
            UINT flags_asItem = MF_DISABLED;
        };

        class MenuItem : public IMenuItem{
        public:
            MenuItem(ID_T id, LPCTSTR name);
            virtual BOOL_T AppendToMenu(HMENU h_menu);
            virtual ID_T GetId();
            virtual LPCTSTR GetDisplayName();
        protected:
            ID_T id;
            LPCTSTR display_name;
        };
        

        typedef util::myTree<ID_T, core::component::IMenuItem> MenuTree;
        typedef util::myTreeNode<ID_T, core::component::IMenuItem> MenuNode;

        class Menu : public IComponent<MenuInstance>, public IMenuItem{
        public:
            Menu(ID_T id, LPCTSTR name, MenuNode * pNode);
            virtual MenuInstance CreateInstance();
            virtual ID_T GetId();
            virtual BOOL_T AppendToMenu(HMENU h_menu);
            virtual LPCTSTR GetDisplayName();
        protected:
            virtual HMENU CreateMenu();
            ID_T id;
            LPCTSTR display_name;
            MenuNode * pNode;
        };

        class PopupMenu : public Menu{
        public:
            PopupMenu(ID_T id, LPCTSTR name, MenuNode * pNode);
            virtual HMENU CreateMenu() override;
        };

        void CreateMenuTree(ID_T id, LPCTSTR display_name,  MenuTree** pptree, bool is_popup_menu);

        void AddChild(IMenuItem* item, MenuNode ** ppNode);

        void AddMenuItem(ID_T id, LPCTSTR display_name, MenuNode ** ppNode);

        void AddSubMenu(ID_T id, LPCTSTR display_name, MenuNode ** ppNode, bool is_popup_menu = false);
    }
}

namespace util{
    // template<>
    // util::myTree<int, core::component::IMenuItem>::~myTree(){

    // }
}